import asyncio
import threading
import time
import pymongo
from . import BinanceStrategyTool
from .BinanceStrategyTool import get_logger, get_asset_type
from .BinanceTradeAPIFactory import BinanceTradeAPIFactory

myclient = pymongo.MongoClient("mongodb://localhost:27017/")
mydb = myclient["binancedb"]
mydb_orders = mydb["alpha"]


class BinanceStrategyInitAlpha(BinanceTradeAPIFactory):
    def __init__(self, UID: int, APIKey: str, SecretKey: str, symbol: str):
        self.nums = {}
        logger = get_logger(str(UID) + '_Strategy_Alpha')
        self.asset_type = get_asset_type(symbol)

        super().__init__(UID=UID, APIKey=APIKey, SecretKey=SecretKey, symbol=symbol, asset_type=self.asset_type,
                         logger=logger)

        self.lock_new_order = False
        self.symbol = symbol

    def _ws_openPosition(self, order):

        price = order.get("o").get("ap")
        date = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(order.get('o').get('T')) / 1000))
        symbol = order.get("o").get("s")
        timeStamp = order.get('o').get('T')
        orderId = order.get("o").get("i")
        positionSide = order.get("o").get("ps")
        volume = order.get("o").get("z")

        openLong = (order.get('o').get('S') == "BUY" and order.get('o').get('ps') == "LONG")
        openShort = (order.get('o').get('S') == "SELL" and order.get('o').get('ps') == "SHORT")
        closeLong = (order.get('o').get('S') == "SELL" and order.get('o').get('ps') == "LONG")
        closeShort = (order.get('o').get('S') == "BUY" and order.get('o').get('ps') == "SHORT")

        if openLong or closeLong:
            mydb_orders.delete_many({"type": "order_price",
                                     "UID": self.UID,
                                     "positionSide": "LONG"})
            mydb_orders.insert_one({"type": "order_price",
                                    "UID": self.UID,
                                    "positionSide": "LONG",
                                    "price": float(price)})

        if openShort or closeShort:
            mydb_orders.delete_many({"type": "order_price",
                                     "UID": self.UID,
                                     "positionSide": "SHORT"})
            mydb_orders.insert_one({"type": "order_price",
                                    "UID": self.UID,
                                    "positionSide": "SHORT",
                                    "price": float(price)})

        if openLong:
            stop_loss_price = 0
            for low in self.nums.get("high_nums"):
                if low <= self.ave_short_price * 0.998:
                    if low > stop_loss_price:  # 取大
                        stop_loss_price = low
            if stop_loss_price == 0:
                stop_loss_price = self.ave_long_price * 0.987

            mydb_orders.delete_many({"type": "stop_loss",
                                     "UID": self.UID,
                                     "positionSide": "LONG"})
            mydb_orders.insert_one({"type": "stop_loss",
                                    "UID": self.UID,
                                    "positionSide": "LONG",
                                    "price": float(stop_loss_price)})

            self.logger.info("【多仓】 数量：" + str(self.all_long_quantity) +
                             " 均价：" + str(self.ave_long_price) +
                             " 止损价：" + str(stop_loss_price))

        if openShort:
            stop_loss_price = 0
            for low in self.nums.get("low_nums"):
                if low >= self.ave_short_price * 1.012:
                    if low < stop_loss_price:  # 取小
                        stop_loss_price = low
            if stop_loss_price == 0:
                stop_loss_price = self.ave_short_price * 1.013

            mydb_orders.delete_many({"type": "stop_loss",
                                     "UID": self.UID,
                                     "positionSide": "SHORT"})
            mydb_orders.insert_one({"type": "stop_loss",
                                    "UID": self.UID,
                                    "positionSide": "SHORT",
                                    "price": float(stop_loss_price)})

            self.logger.info("【空仓】 数量：" + str(self.all_short_quantity) +
                             " 均价：" + str(self.ave_short_price) +
                             " 止损价：" + str(stop_loss_price))

    def last_long_price(self):
        for var in mydb_orders.find({"type": "order_price", "UID": self.UID, "positionSide": "LONG"}):
            return float(var.get("price"))
        return 999

    def last_short_price(self):
        for var in mydb_orders.find({"type": "order_price", "UID": self.UID, "positionSide": "SHORT"}):
            return float(var.get("price"))
        return 0

    def long_stop_loss_price(self, remove=False):
        if remove:
            mydb_orders.delete_many({"type": "stop_loss",
                                     "UID": self.UID,
                                     "positionSide": "LONG"})

        for var in mydb_orders.find({"type": "stop_loss", "UID": self.UID, "positionSide": "LONG"}):
            return float(var.get("price"))
        return 0

    def short_stop_loss_price(self, remove=False):
        if remove:
            mydb_orders.delete_many({"type": "stop_loss",
                                     "UID": self.UID,
                                     "positionSide": "SHORT"})

        for var in mydb_orders.find({"type": "stop_loss", "UID": self.UID, "positionSide": "SHORT"}):
            return float(var.get("price"))
        return 999

    @staticmethod
    def __quantity(score, value, now_price):
        if score >= 4 or score <= -4:
            return (value / now_price) * 3
        if score == 3 or score == -3:
            return (value / now_price) * 2
        if score == 2 or score == -2:
            return value / now_price

    async def __openLongStrategy(self, now_price, score):
        if self.lock_new_order:
            return False

        if now_price <= self.last_long_price() * 0.995:
            value = self.get_asset_value(self.asset_type)
            quantity = self.__quantity(score, value, now_price)
            if self.all_long_quantity < (value / now_price) * 6:
                pass
                await self.openLong(quantity)  # 开多
            else:
                self.lock_new_order = True

        return False

    async def __openShortStrategy(self, now_price, score):
        if self.lock_new_order:
            return False

        if now_price >= self.last_short_price() * 1.005:
            value = self.get_asset_value(self.asset_type)
            quantity = self.__quantity(score, value, now_price)

            if self.all_long_quantity < (value / now_price) * 6:
                pass
                await self.openShort(quantity)  # 开空
            else:
                self.lock_new_order = True

        return False

    async def __closeLongStrategy(self, now_price):
        if self.all_long_quantity <= 0:
            return False

        if now_price <= self.ave_long_price * 1.005:
            if await self.closeLong(int(self.all_long_quantity) + 1):  # 平多
                self.long_stop_loss_price(remove=True)
                self.lock_new_order = False

        return False

    async def __closeShortStrategy(self, now_price):

        if self.all_short_quantity <= 0:
            return False

        if now_price <= self.ave_short_price * 0.995:
            if await self.closeShort(int(self.all_short_quantity) + 1):  # 平空
                self.short_stop_loss_price(remove=True)
                self.lock_new_order = False

        return False

    async def execute(self, score, now_price, nums):
        self.nums = nums
        if score >= 2:
            await self.__openShortStrategy(now_price, score)
            await self.__closeLongStrategy(now_price)
        if score <= -2:
            await self.__openLongStrategy(now_price, score)
            await self.__closeShortStrategy(now_price)

        if self.all_short_quantity >= 0 and now_price >= self.short_stop_loss_price():
            if await self.closeShort(int(self.all_short_quantity) + 1):  # 平空
                self.logger.info("空仓止损")
                self.short_stop_loss_price(remove=True)
                self.lock_new_order = False

        if self.all_long_quantity >= 0 and now_price <= self.long_stop_loss_price():
            if await self.closeLong(int(self.all_long_quantity) + 1):  # 平多
                self.logger.info("空仓止损")
                self.long_stop_loss_price(remove=True)
                self.lock_new_order = False
        self.execute_end()

    def execute_end(self):
        pass
